home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / music / 7 / pascal / strval.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-11-19  |  7.1 KB  |  330 lines

  1.  
  2.  
  3.  
  4. {*  THIS IS A PROGRAM, TAKE OUT THE MAIN ROUTINE TO USE JUST THE FUNCTIONS *}
  5.  
  6. Program LalaBlahLala(InThoughTheOutDoor,OutThroughTheInDoor);
  7.  
  8. Var
  9.   TestSt:  String;
  10.   TestRl:  Real;
  11.  
  12.  
  13. {***
  14.  *   Floating Point Conversion routines.
  15.  *   From Real to String and String to Real
  16.  *
  17.  *   By Kevin L. McGrath
  18.  ***}
  19.  
  20. PROCEDURE Str(Value: Real; VAR St: String);
  21.  
  22. {* Notes:
  23.  *   This routine is only accurate up to 9 digits becuase of the LongTrunc.
  24.  *   It HAD rounding errors, but they are now fixed (with the LongTrunc)
  25.  *
  26.  * O.S.S. Pascals Floating Point Format:
  27.  *   This is just a guess, but here goes...
  28.  *   One byte of exponent biased by 128 to give a +38 to -38 range.
  29.  *   Fourty bits of mantissa to give 11 digits of accuracy, One bit sign.
  30.  *   Most floating points are normalized to the left, with the point between
  31.  *   the most significant bit of the mantissa and the second most, so I think
  32.  *   this is two.  To find out, just plug out a routine that has a pointer
  33.  *   to a real, coerce's it into a pointer to a record structure of byte like
  34.  *   this:
  35.  *     Record
  36.  *       Exponent:      Byte;
  37.  *       MantissaOne:   Long;
  38.  *       MantissaTwo:   Long;
  39.  *       MantissaThree: Long;
  40.  *     End;
  41.  *   then you can extract the exponent and mantissa just by doing a
  42.  *   "Ptr.Exponent" or somethin like that.  Well, I haven't had time to get
  43.  *   that fancy with this, but I have used this routine and am sure it works.
  44.  *   Hope you guys at O.S.S. can vert it to some kind of normal ASM function!
  45.  *      Good Luck...   (Nice Compiler)
  46.  *      Call me if there are any probs, dig?
  47.  *}
  48.  
  49.  
  50. Const
  51.   Max_Digits    = 09;
  52.   Max_Exponent  = 38;
  53.  
  54. Var
  55.   Val:          Real;
  56.   TempInt,
  57.   Sig_Digits,
  58.   Dec_Exp,
  59.   I:            Integer;
  60.   Digits:       String;
  61.  
  62. Begin
  63.   Val := Abs(Value);
  64.   Dec_Exp := 0;
  65.  
  66.   {* Get the exponent without Natural Log (Ln doesn't seem to work fer me) *}
  67.  
  68.   If (Val < 1) And (Val > 0) Then
  69.   Begin
  70.     For I := 0 To (Max_Exponent-1) Do
  71.       If (Val < (1/PwrOfTen(I))) And (Val >= (1/PwrOfTen(I+1))) Then
  72.         Dec_Exp := -(I+1);
  73.     Val := Val * PwrOfTen(Abs(Dec_Exp)-1);
  74.   End
  75.   Else
  76.   Begin
  77.     For I := 0 To (Max_Exponent-1) Do
  78.       If (Val >= PwrOfTen(I)) And (Val < PwrOfTen(I+1)) Then
  79.         Dec_Exp := I;
  80.     Val := Val / PwrOfTen(Dec_Exp+1);
  81.   End;
  82.  
  83. { Get decimal digits by stripping }
  84.  
  85.   Digits := '';
  86.   St := '';
  87.  
  88.   For I := Max_Digits DownTo 1 Do
  89.   Begin
  90.     { Take care of rounding problems }
  91.  
  92.     Val := Long_Trunc(Val*PwrOfTen(I)+0.5)/PwrOfTen(I);
  93.  
  94.     Val := Val*10.0;
  95.     Digits := ConCat(Digits,Chr(48+Trunc(Val)));
  96.     Val := Val-Trunc(Val);
  97.  
  98.     { Take care of rounding problems }
  99.  
  100.     Val := Long_Trunc(Val*PwrOfTen(I)+0.5)/PwrOfTen(I);
  101.  
  102.   End;
  103.  
  104. { Format and put result in St }
  105. { Put sign }
  106.  
  107.   If Value < 0 Then St := '-';
  108.  
  109. { Compute significant digits }
  110.  
  111.   Sig_Digits := Max_Digits;
  112.   I := Max_Digits - 1;
  113.   While ((Digits[I]='0') And (I>0)) Do
  114.   Begin
  115.     Sig_Digits := Sig_Digits - 1;
  116.     I := I - 1;
  117.   End;
  118.   Sig_Digits := Sig_Digits - 1;
  119.  
  120. { Put in exponential or non-exonential }
  121.  
  122.   If ((Sig_Digits-Max_Digits)<=Dec_Exp) And (Dec_Exp<=Max_Digits) Then
  123.   Begin
  124.     { Non-exponental form }
  125.     { Put decimal point and leading zeros for numbers with negative exponents }
  126.  
  127.     If Dec_Exp < 0 Then
  128.     Begin
  129.       St := ConCat(St,'.');
  130.       For I := 1 To -Dec_Exp-1 Do
  131.         St := ConCat(St,'0');
  132.     End;
  133.  
  134.     { Put significant digits }
  135.  
  136.     St := ConCat(St,Digits[1]);
  137.     For I := 1 To Sig_Digits-1 Do
  138.     Begin
  139.       If Dec_Exp = 0 Then
  140.         St := ConCat(St,'.');
  141.       St := ConCat(St,Digits[I+1]);
  142.       Dec_Exp := Dec_Exp - 1;
  143.     End;
  144.  
  145.     { Put trailing zeros }
  146.  
  147.     While Dec_Exp > 0 Do
  148.     Begin
  149.       St := ConCat(St,'0');
  150.       Dec_Exp := Dec_Exp - 1;
  151.     End;
  152.   End
  153.   Else
  154.   Begin
  155.     { Exponental form }
  156.     { Put first digit }
  157.  
  158.     St := ConCat(St,Digits[1]);
  159.  
  160.     { Put decimal point }
  161.  
  162.     If Sig_Digits > 1 Then
  163.       St := ConCat(St,'.');
  164.  
  165.     { Put remaining significant digits }
  166.  
  167.     For I := 1 To (Sig_Digits - 1) Do
  168.       St := ConCat(St,Digits[I+1]);
  169.  
  170.     { Put the 'E' for the exponent }
  171.  
  172.     St := ConCat(St,'E');
  173.  
  174.     { Put exponents sign }
  175.  
  176.     If Dec_Exp >= 0 Then
  177.       St := ConCat(St,'+')
  178.     Else
  179.     Begin
  180.       St := ConCat(St,'-');
  181.       Dec_Exp := Abs(Dec_Exp);
  182.     End;
  183.  
  184.     { Put the exponent }
  185.  
  186.     If Dec_Exp >= 10 Then
  187.     Begin
  188.       St := ConCat(St,Chr(48+(Dec_Exp Div 10)));
  189.       St := ConCat(St,Chr(48+Dec_Exp-((Dec_Exp Div 10) * 10)));
  190.     End
  191.     Else
  192.     Begin
  193.       St := ConCat(St,'0');
  194.       St := ConCat(St,Chr(48+Dec_Exp));
  195.     End;
  196.   End;
  197. End;
  198.  
  199.  
  200. FUNCTION Val( St: String): Real;
  201.  
  202. Const
  203.   Max_Digits    = 09;
  204.  
  205. Var
  206.   Dec_Exp,
  207.   Exp_Value,
  208.   Count,
  209.   Position:     Integer;
  210.   Chr:          Char;
  211.   Result:       Real;
  212.   Dec_Sign,
  213.   Exp_Sign:     Boolean;
  214.  
  215.   PROCEDURE Add_Digit;
  216.  
  217.   Begin
  218.     Result := (Result * 10) + (Ord(Chr) & $0F);
  219.   End;
  220.  
  221.   PROCEDURE Read_Chr;
  222.  
  223.   Begin
  224.     Position := Position + 1;
  225.     If Position > Length(St) Then
  226.       Chr := 'X'
  227.     Else
  228.       Chr := St[Position];
  229.   End;
  230.  
  231. Begin
  232.   Position := 0;
  233.   Read_Chr;
  234.   Result := 0.0;
  235.  
  236. { Get sign }
  237.  
  238.   Dec_Sign := False;
  239.   If Chr = '+' Then Read_Chr;
  240.   If Chr = '-' Then
  241.   Begin
  242.     Read_Chr;
  243.     Dec_Sign := True;
  244.   End;
  245.  
  246. { Get digits to left of decimal point }
  247.  
  248.   Dec_Exp := 0;
  249.   Count := Max_Digits;
  250.   While ('0' <= Chr) And (Chr <= '9') Do
  251.   Begin
  252.     If Count > 0 Then
  253.     Begin
  254.       Add_Digit;
  255.       Count := Count - 1;
  256.     End
  257.     Else
  258.       Dec_Exp := Dec_Exp + 1;
  259.     Read_Chr;
  260.   End;
  261.  
  262. { Get digits to the right of decimal point }
  263.  
  264.   If Chr = '.' Then
  265.   Begin
  266.     Read_Chr;
  267.     While ('0' <= Chr) And (Chr <= '9') Do
  268.     Begin
  269.       If Count > 0 Then
  270.       Begin
  271.         Add_Digit;
  272.         Dec_Exp := Dec_Exp - 1;
  273.         Count := Count - 1;
  274.       End;
  275.       Read_Chr;
  276.     End;
  277.   End;
  278.  
  279. { Get exponent part }
  280.  
  281.   If (Chr = 'E') Or (Chr = 'e') Then
  282.   Begin
  283.     Read_Chr;
  284.     Exp_Sign := False;
  285.     If Chr = '+' Then Read_Chr;
  286.     If Chr = '-' Then
  287.     Begin
  288.       Read_Chr;
  289.       Exp_Sign := True;
  290.     End;
  291.     Exp_Value := 0;
  292.     If ('0'<=Chr) And (Chr<='9') Then Exp_Value := (Ord(Chr) & $0F)*10;
  293.     Read_Chr;
  294.     If ('0'<=Chr) And (Chr<='9') Then Exp_Value := Exp_Value+(Ord(Chr) & $0F);
  295.     If (Chr = 'X') And (Exp_Value >= 10) Then Exp_Value := Exp_Value Div 10;
  296.     If Exp_Sign Then
  297.       Dec_Exp := Dec_Exp - Exp_Value
  298.     Else
  299.       Dec_Exp := Dec_Exp + Exp_Value;
  300.   End;
  301.  
  302. { Multiply or divide Result by power of 10 specified by Dec_Exp }
  303.  
  304.   If Dec_Exp > 0 Then
  305.     Result := Result * PwrOfTen(Dec_Exp)
  306.   Else
  307.     Result := Result / PwrOfTen(Abs(Dec_Exp));
  308.  
  309.   If Dec_Sign Then Result := -Result;
  310.  
  311.   Val := Result;
  312.  
  313. End;
  314.  
  315.  
  316. {*  MAIN ROUTINE  *}
  317.  
  318. Begin
  319.   TestRl := 0.0;
  320.   While (TestRl <> 9.0) do
  321.   Begin
  322.     WriteLn('Test for Val and Str. Enter a "9" to stop.');
  323.     Write('Enter a number:');
  324.     ReadLn(TestSt);
  325.     TestRl := Val(TestSt);
  326.     Str(TestRl,TestSt);
  327.     WriteLn('Real number as a string:',TestSt);
  328.   End;
  329. End.
  330. RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR